package bancosys.tec.services.api;

import java.math.BigDecimal;

import jmine.tec.services.annotations.Execution;
import jmine.tec.services.annotations.ServiceImplementor;
import jmine.tec.services.api.ActionsEnum;
import jmine.tec.services.api.ServiceExecutionException;
import bancosys.tec.exception.LocalizedMessageHolder;
import bancosys.tec.persist.base.enumx.IntValuedEnum;
import bancosys.tec.persist.base.enumx.StringValuedEnum;
import bancosys.tec.utils.date.Date;

/**
 * Classe abstrata para serviços de validação.
 * 
 * @author lundberg
 */
@ServiceImplementor(action = ActionsEnum.VALIDAR)
public abstract class AbstractValidationService {
    private ServiceValidator validator;

    /**
     * Executa o serviço de validação.
     * 
     * @throws ServiceExecutionException ServiceExecutionException
     */
    @Execution
    public final void execute() throws ServiceExecutionException {
        if (!this.shouldCheckNullParameters()) {
            this.validator = new IgnoreNullServiceValidator();
        } else {
            this.validator = new ServiceValidator();
        }
        this.validate();
        this.validator.throwValidationException();
    }

    /**
     * Efetua as validações necessárias
     * 
     * @throws ServiceExecutionException ServiceExecutionException
     */
    protected abstract void validate() throws ServiceExecutionException;

    /**
     * Hook que pode ser sobre-escrito pelas sub-classes para informar se não devem ser executadas as validações se o parametro <i>got</i>
     * for <code>null</code>. <br>
     * Util geralmente em serviços que são exclusivamente de validação e seus parametros são opcionais.
     * 
     * @return <code>true</code> se parametros <code>null</code> devem ser validados, <code>false</code> caso contrario
     */
    protected boolean shouldCheckNullParameters() {
        return true;
    }

    /**
     * @param fieldName fieldName
     * @param expected expected
     * @param got got
     * @param precision precision
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertEquals(java.lang.String,
     * java.math.BigDecimal, java.math.BigDecimal, double)
     */
    public void assertEquals(String fieldName, BigDecimal expected, BigDecimal got, double precision) {
        this.validator.assertEquals(fieldName, expected, got, precision);
    }

    /**
     * @param fieldName fieldName
     * @param expected expected
     * @param got got
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertEquals(java.lang.String,
     * java.math.BigDecimal, java.math.BigDecimal)
     */
    public void assertEquals(String fieldName, BigDecimal expected, BigDecimal got) {
        this.validator.assertEquals(fieldName, expected, got);
    }

    /**
     * @param fieldName fieldName
     * @param expected expected
     * @param got got
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertEquals(java.lang.String,
     * bancosys.tec.utils.date.Date, bancosys.tec.utils.date.Date)
     */
    public void assertEquals(String fieldName, Date expected, Date got) {
        this.validator.assertEquals(fieldName, expected, got);
    }

    /**
     * @param fieldName fieldName
     * @param expected expected
     * @param got got
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertEquals(java.lang.String,
     * bancosys.tec.persist.base.enumx.IntValuedEnum, bancosys.tec.persist.base.enumx.IntValuedEnum)
     */
    public void assertEquals(String fieldName, IntValuedEnum expected, IntValuedEnum got) {
        this.validator.assertEquals(fieldName, expected, got);
    }

    /**
     * @param fieldName fieldName
     * @param expected expected
     * @param got got
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertEquals(java.lang.String,
     * java.lang.Object, java.lang.Object)
     */
    public void assertEquals(String fieldName, Object expected, Object got) {
        this.validator.assertEquals(fieldName, expected, got);
    }

    /**
     * @param fieldName fieldName
     * @param expected expected
     * @param got got
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertEquals(java.lang.String,
     * bancosys.tec.persist.base.enumx.StringValuedEnum, bancosys.tec.persist.base.enumx.StringValuedEnum)
     */
    public void assertEquals(String fieldName, StringValuedEnum expected, StringValuedEnum got) {
        this.validator.assertEquals(fieldName, expected, got);
    }

    /**
     * @param fieldName fieldName
     * @param expected expected
     * @param got got
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertEqualsExact(java.lang.String,
     * java.math.BigDecimal, java.math.BigDecimal)
     */
    public void assertEqualsExact(String fieldName, BigDecimal expected, BigDecimal got) {
        this.validator.assertEqualsExact(fieldName, expected, got);
    }

    /**
     * @param fieldName fieldName
     * @param condition condition
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertFalse(java.lang.String, boolean)
     */
    public void assertFalse(String fieldName, boolean condition) {
        this.validator.assertFalse(fieldName, condition);
    }

    /**
     * @param fieldName fieldName
     * @param obj obj
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertNotNull(java.lang.String,
     * java.lang.String, java.lang.Object)
     */
    public void assertNotNull(String fieldName, Object obj) {
        this.validator.assertNotNull(fieldName, obj);
    }

    /**
     * @param fieldName fieldName
     * @param obj obj
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertNull(java.lang.String,
     * java.lang.String, java.lang.Object)
     */
    public void assertNull(String fieldName, Object obj) {
        this.validator.assertNull(fieldName, obj);
    }

    /**
     * @param fieldName fieldName
     * @param condition condition
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#assertTrue(java.lang.String, boolean)
     */
    public void assertTrue(String fieldName, boolean condition) {
        this.validator.assertTrue(fieldName, condition);
    }

    /**
     * @param bundleName bundleName
     * @param messageKey messageKey
     * @param args argumentos
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#fail(java.lang.String, java.lang.String)
     * @deprecated use LocalizedMessageHolder
     */
    @Deprecated
    public void fail(String bundleName, String messageKey, Object... args) {
        this.validator.fail(bundleName, messageKey, args);
    }

    /**
     * @param message message
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#fail(java.lang.String, java.lang.String)
     */
    public void fail(LocalizedMessageHolder message) {
        this.validator.fail(message);
    }

    /**
     * @param expected expected
     * @param got got
     * @param precision precision
     * @return boolean
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#isEquals(java.math.BigDecimal,
     * java.math.BigDecimal, double)
     */
    public boolean isEquals(BigDecimal expected, BigDecimal got, double precision) {
        return this.validator.isEquals(expected, got, precision);
    }

    /**
     * @param expected expected
     * @param got got
     * @return boolean
     * @see bancosys.tec.services.api.business.financ.carteira.services.validar.ServiceValidator#isEquals(java.math.BigDecimal,
     * java.math.BigDecimal)
     */
    public boolean isEquals(BigDecimal expected, BigDecimal got) {
        return this.validator.isEquals(expected, got);
    }

    /**
     * @return if there are validation errors.
     */
    protected boolean hasValidationErrors() {
        return this.validator.hasErrors();
    }
}
